from rest_framework import serializers
from django.core.files.uploadedfile import UploadedFile as DjangoUploadedFile
from apps.core.models import UploadedFile, Template
from typing import Dict, Any


class FileUploadSerializer(serializers.Serializer):
    """
    文件上传序列化器
    """
    files = serializers.ListField(
        child=serializers.FileField(),
        required=True,
        help_text="上传的文件列表"
    )
    
    file_type = serializers.ChoiceField(
        choices=[
            ('source', '源文件'),
            ('template', '模板文件'),
            ('result', '结果文件')
        ],
        default='source',
        help_text="文件类型"
    )
    
    template_id = serializers.IntegerField(
        required=False,
        allow_null=True,
        help_text="关联模板ID"
    )
    
    def validate_template_id(self, value):
        """
        验证模板ID
        """
        if value is not None:
            try:
                Template.objects.get(id=value)
            except Template.DoesNotExist:
                raise serializers.ValidationError("指定的模板不存在")
        return value
    
    def validate_files(self, value):
        """
        验证文件列表
        """
        if not value:
            raise serializers.ValidationError("至少需要上传一个文件")
        
        # 检查文件数量限制
        if len(value) > 10:
            raise serializers.ValidationError("一次最多只能上传10个文件")
        
        return value


class FileListSerializer(serializers.ModelSerializer):
    """
    文件列表序列化器
    """
    template_name = serializers.CharField(
        source='template.name',
        read_only=True,
        allow_null=True
    )
    
    file_size = serializers.SerializerMethodField()
    file_url = serializers.SerializerMethodField()
    uploaded_at_formatted = serializers.SerializerMethodField()
    file_extension = serializers.SerializerMethodField()
    
    class Meta:
        model = UploadedFile
        fields = [
            'id', 'original_name', 'file_type', 'template_name',
            'file_size', 'file_url', 'created_at', 'uploaded_at_formatted',
            'file_extension'
        ]
    
    def get_file_size(self, obj) -> int:
        """
        获取文件大小
        """
        try:
            return obj.file.size if obj.file else 0
        except:
            return 0
    
    def get_file_url(self, obj) -> str:
        """
        获取文件URL
        """
        try:
            return obj.file.url if obj.file else None
        except:
            return None
    
    def get_uploaded_at_formatted(self, obj) -> str:
        """
        格式化上传时间
        """
        return obj.created_at.strftime('%Y-%m-%d %H:%M:%S')
    
    def get_file_extension(self, obj) -> str:
        """
        获取文件扩展名
        """
        import os
        return os.path.splitext(obj.original_name)[1].lower()


class FileInfoSerializer(serializers.Serializer):
    """
    文件详细信息序列化器
    """
    id = serializers.IntegerField()
    original_name = serializers.CharField()
    file_type = serializers.CharField()
    template = serializers.CharField(allow_null=True)
    created_at = serializers.DateTimeField()
    file_url = serializers.CharField(allow_null=True)
    file_info = serializers.DictField(default=dict)
    
    def to_representation(self, instance):
        """
        自定义序列化输出
        """
        data = super().to_representation(instance)
        
        # 格式化文件信息
        file_info = data.get('file_info', {})
        if file_info:
            # 格式化文件大小
            if 'file_size' in file_info:
                size = file_info['file_size']
                if size > 1024 * 1024:
                    file_info['file_size_formatted'] = f"{size / 1024 / 1024:.2f} MB"
                elif size > 1024:
                    file_info['file_size_formatted'] = f"{size / 1024:.2f} KB"
                else:
                    file_info['file_size_formatted'] = f"{size} B"
            
            # 格式化修改时间
            if 'modified_time' in file_info:
                import datetime
                try:
                    dt = datetime.datetime.fromtimestamp(file_info['modified_time'])
                    file_info['modified_time_formatted'] = dt.strftime('%Y-%m-%d %H:%M:%S')
                except:
                    pass
        
        return data


class FilePreviewSerializer(serializers.Serializer):
    """
    文件预览序列化器
    """
    file_id = serializers.IntegerField(help_text="文件ID")
    sheet_name = serializers.CharField(
        required=False,
        allow_blank=True,
        help_text="工作表名称（Excel文件）"
    )
    max_rows = serializers.IntegerField(
        default=100,
        min_value=1,
        max_value=1000,
        help_text="最大预览行数"
    )
    
    def validate_file_id(self, value):
        """
        验证文件ID
        """
        try:
            UploadedFile.objects.get(id=value)
        except UploadedFile.DoesNotExist:
            raise serializers.ValidationError("指定的文件不存在")
        return value


class FilePreviewDataSerializer(serializers.Serializer):
    """
    文件预览数据序列化器
    """
    headers = serializers.ListField(
        child=serializers.CharField(),
        help_text="表头列表"
    )
    
    data = serializers.ListField(
        child=serializers.ListField(
            child=serializers.CharField(allow_null=True)
        ),
        help_text="数据行列表"
    )
    
    total_rows = serializers.IntegerField(help_text="总行数")
    total_columns = serializers.IntegerField(help_text="总列数")
    sheet_name = serializers.CharField(
        allow_null=True,
        help_text="工作表名称"
    )
    
    file_info = serializers.DictField(
        default=dict,
        help_text="文件信息"
    )


class BatchFileOperationSerializer(serializers.Serializer):
    """
    批量文件操作序列化器
    """
    file_ids = serializers.ListField(
        child=serializers.IntegerField(),
        min_length=1,
        help_text="文件ID列表"
    )
    
    operation = serializers.ChoiceField(
        choices=[
            ('delete', '删除'),
            ('move', '移动'),
            ('copy', '复制')
        ],
        help_text="操作类型"
    )
    
    target_template_id = serializers.IntegerField(
        required=False,
        allow_null=True,
        help_text="目标模板ID（移动/复制操作）"
    )
    
    def validate_file_ids(self, value):
        """
        验证文件ID列表
        """
        # 检查文件是否存在
        existing_files = UploadedFile.objects.filter(id__in=value)
        existing_ids = set(existing_files.values_list('id', flat=True))
        missing_ids = set(value) - existing_ids
        
        if missing_ids:
            raise serializers.ValidationError(
                f"以下文件不存在: {list(missing_ids)}"
            )
        
        return value
    
    def validate(self, attrs):
        """
        交叉验证
        """
        operation = attrs.get('operation')
        target_template_id = attrs.get('target_template_id')
        
        # 移动和复制操作需要目标模板
        if operation in ['move', 'copy'] and not target_template_id:
            raise serializers.ValidationError(
                "移动和复制操作需要指定目标模板"
            )
        
        # 验证目标模板是否存在
        if target_template_id:
            try:
                Template.objects.get(id=target_template_id)
            except Template.DoesNotExist:
                raise serializers.ValidationError("指定的目标模板不存在")
        
        return attrs


class FileStatisticsSerializer(serializers.Serializer):
    """
    文件统计信息序列化器
    """
    total_files = serializers.IntegerField(help_text="总文件数")
    source_files = serializers.IntegerField(help_text="源文件数")
    template_files = serializers.IntegerField(help_text="模板文件数")
    result_files = serializers.IntegerField(help_text="结果文件数")
    
    total_size = serializers.IntegerField(help_text="总文件大小（字节）")
    total_size_formatted = serializers.CharField(help_text="格式化的总文件大小")
    
    recent_uploads = serializers.IntegerField(help_text="最近24小时上传数")
    
    file_type_distribution = serializers.DictField(
        help_text="文件类型分布"
    )
    
    upload_trend = serializers.ListField(
        child=serializers.DictField(),
        help_text="上传趋势（最近7天）"
    )


class FileSearchSerializer(serializers.Serializer):
    """
    文件搜索序列化器
    """
    keyword = serializers.CharField(
        required=False,
        allow_blank=True,
        help_text="搜索关键词"
    )
    
    file_type = serializers.ChoiceField(
        choices=[
            ('', '全部'),
            ('source', '源文件'),
            ('template', '模板文件'),
            ('result', '结果文件')
        ],
        required=False,
        allow_blank=True,
        help_text="文件类型"
    )
    
    template_id = serializers.IntegerField(
        required=False,
        allow_null=True,
        help_text="模板ID"
    )
    
    date_from = serializers.DateField(
        required=False,
        allow_null=True,
        help_text="开始日期"
    )
    
    date_to = serializers.DateField(
        required=False,
        allow_null=True,
        help_text="结束日期"
    )
    
    min_size = serializers.IntegerField(
        required=False,
        allow_null=True,
        min_value=0,
        help_text="最小文件大小（字节）"
    )
    
    max_size = serializers.IntegerField(
        required=False,
        allow_null=True,
        min_value=0,
        help_text="最大文件大小（字节）"
    )
    
    page = serializers.IntegerField(
        default=1,
        min_value=1,
        help_text="页码"
    )
    
    page_size = serializers.IntegerField(
        default=20,
        min_value=1,
        max_value=100,
        help_text="每页数量"
    )
    
    order_by = serializers.ChoiceField(
        choices=[
            ('-created_at', '上传时间（降序）'),
        ('created_at', '上传时间（升序）'),
            ('original_name', '文件名（升序）'),
            ('-original_name', '文件名（降序）'),
            ('file_type', '文件类型（升序）')
        ],
        default='-created_at',
        help_text="排序方式"
    )
    
    def validate(self, attrs):
        """
        交叉验证
        """
        date_from = attrs.get('date_from')
        date_to = attrs.get('date_to')
        min_size = attrs.get('min_size')
        max_size = attrs.get('max_size')
        
        # 验证日期范围
        if date_from and date_to and date_from > date_to:
            raise serializers.ValidationError(
                "开始日期不能晚于结束日期"
            )
        
        # 验证文件大小范围
        if min_size is not None and max_size is not None and min_size > max_size:
            raise serializers.ValidationError(
                "最小文件大小不能大于最大文件大小"
            )
        
        return attrs